﻿#include "chartpane.h"
#include "ui_chartpane.h"
#include "qwdialogpen.h"

ChartPane::ChartPane(QWidget* parent)
    : QWidget(parent)
{
    ui = new Ui::ChartPane();
    ui->setupUi(this);
    ui->btn_up->setEnabled(false);
    ui->btn_styleSet->hide();
    init();
    m_nMax = 0;
    m_nType = 0;
    m_nIndex = 0;
    m_nRow = 0;
}

ChartPane::~ChartPane()
{
    delete ui;
}

bool ChartPane::getTabState(QString file)
{
    m_dealData.initDB();
    bool bState = m_dealData.isCreateTab(file);
    m_dealData.disDB();
    return bState;
}

void ChartPane::setFile(QString file, int type)
{
    if (file.isEmpty()) {
        return;
    }
    m_sFile = file;
    m_nType = type;
    if (type < 2) {
        m_dealData.initData(m_sFile, m_nIndex);
        ui->btn_up->show();
        ui->btn_down->show();
    }
    else {
        ui->btn_up->hide();
        ui->btn_down->hide();
    }
    dealData();
}

void ChartPane::drawLine()
{
    ui->pgBar_data->hide();
    if (m_chartData.size() == 0)
    {
        ui->btn_down->setEnabled(false);
        return;
    }
    ui->btn_down->setEnabled(true);
    ui->page_2->hide();
    ui->chartInfo->hide();
    QLineSeries* series = new QLineSeries();

    for (int i = 0; i < m_chartData.size(); i++)
    {
        *series << QPointF(i, m_chartData.value(QString::number(i))[TM]);
    }
    m_chart->addSeries(series);
    m_chart->legend()->hide();

    QValueAxis* axisX = new QValueAxis();
    axisX->setTitleText(tr("Data Point"));
    axisX->setLabelFormat("%i");
    axisX->setTickCount(series->count());
    m_chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);



    QValueAxis* axisY = new QValueAxis();
    curAxis = axisY;
    axisY->setRange(m_minValue, m_maxValue + 200);
    axisY->setTitleText(m_label);
    axisY->setLabelFormat("%ims");
    axisY->setTickCount(8);

    axisY->setGridLineVisible(false);
    axisY->applyNiceNumbers();
    m_chart->setAxisY(axisY, series);
    m_chart->legend()->setAlignment(Qt::AlignLeft);


    m_chart->setTitle(m_title);

    foreach(QLegendMarker * marker, m_chart->legend()->markers()) {
        QObject::disconnect(marker, SIGNAL(clicked()), this, SLOT(on_LegendMarkerClicked()));
        QObject::connect(marker, SIGNAL(clicked()), this, SLOT(on_LegendMarkerClicked()));
    }
}

void ChartPane::drawBar()
{
    ui->pgBar_data->hide();
    if (m_chartData.size() == 0)
    {
        ui->btn_down->setEnabled(false);
        return;
    }
    if (m_labels.empty())
    {

        QStringList labels = autoGenLabels(m_chartData);
        setLabels(labels);
        return drawBar();
    }
    ui->page_2->show();
    ui->btn_down->setEnabled(true);
    ui->chartInfo->hide();
    QMap<QString, QBarSet*> barSets;
    foreach(QString label, m_labels)
    {
        QBarSet* barSet = new QBarSet(label);
        barSets.insert(label, barSet);
    }

    for (int nRow = 0; nRow < m_model->rowCount(); nRow++)
    {
        for (int nCol = 0; nCol < m_model->columnCount(); nCol++)
        {
            QString label = m_labels.at(nCol);
            if (Q_NULLPTR != barSets.value(label))
            {
                barSets.value(label)->append(m_model->item(nRow, nCol)->data().toLongLong());
            }
        }
    }

    if (m_barOrientation == VERTICAL_BAR)
    {
        QBarSeries* series = new QBarSeries();
        curSeries = series;
        foreach(QString setKey, barSets.keys())
        {
            series->append(barSets.value(setKey));
        }
        m_chart->addSeries(series);

        QStringList categories = m_chartData.keys();

        QBarCategoryAxis* axisX = new QBarCategoryAxis();
        axisX->setTitleText(tr("Time Point"));
        axisX->append(categories);
        axisX->setGridLineVisible(false);
        m_chart->setAxisX(axisX, series);
        axisX->setRange(categories.at(0), categories.at(categories.size() - 1));

        QValueAxis* axisY = new QValueAxis();
        curAxis = axisY;
        axisY->setRange(m_minValue, m_maxValue);
        axisY->setTitleText(m_label);
        axisY->setGridLineVisible(false);
        axisY->applyNiceNumbers();
        m_chart->setAxisY(axisY, series);


        series->setLabelsVisible(true);
        series->setLabelsPosition(QAbstractBarSeries::LabelsInsideEnd);
    }
    else
    {
        QHorizontalBarSeries* series = new QHorizontalBarSeries();
        curHorSeries = series;
        foreach(QString setKey, barSets.keys())
        {
            series->append(barSets.value(setKey));
        }
        m_chart->addSeries(series);

        QStringList categories = m_chartData.keys();

        QBarCategoryAxis* axisY = new QBarCategoryAxis();
        axisY->append(categories);
        axisY->setGridLineVisible(false);
        m_chart->setAxisY(axisY, series);
        axisY->setRange(categories.at(0), categories.at(categories.size() - 1));

        QValueAxis* axisX = new QValueAxis();
        curAxis = axisX;
        axisX->setRange(m_minValue, m_maxValue);
        axisX->setTitleText(m_label);
        axisX->setGridLineVisible(false);
        axisX->applyNiceNumbers();
        m_chart->setAxisX(axisX, series);

        m_chart->legend()->setAlignment(Qt::AlignTop);

        series->setLabelsVisible(true);
        series->setLabelsPosition(QAbstractBarSeries::LabelsInsideEnd);
    }

    m_chart->legend()->setVisible(false);
    m_chart->setTitle(m_title);

    foreach(QLegendMarker * marker, m_chart->legend()->markers()) {
        QObject::disconnect(marker, SIGNAL(clicked()), this, SLOT(on_LegendMarkerClicked()));
        QObject::connect(marker, SIGNAL(clicked()), this, SLOT(on_LegendMarkerClicked()));
    }
}

void ChartPane::drawSpline()
{
    QMap<int, int> barDatas = m_barDatas;
    if (!m_chartSplineData.size() && !barDatas.size())
    {
        ui->btn_down->setEnabled(false);
        return;
    }

    ui->btn_up->setEnabled(false);
    ui->btn_down->setEnabled(false);
    ui->page_2->hide();
    ui->chartInfo->setText(m_dealData.m_strInfo);
    ui->chartInfo->show();

    QSplineSeries* splineSeries = new QSplineSeries();
    splineSeries->setColor(QColor(0, 100, 255));

    QMap<double, double>::iterator iter = m_chartSplineData.begin();


    m_chart->addSeries(splineSeries);

    while (iter != m_chartSplineData.end())
    {
        qDebug() << "Iterator " << iter.key() << ":" << iter.value();
        splineSeries->append(QPointF((int)iter.key(), iter.value()));
        iter++;
    }
    splineSeries->setUseOpenGL(true);


    QValueAxis* axisX = new QValueAxis;
    axisX->setRange(0, m_nMax);
    axisX->setTickCount(10);
    axisX->setLabelFormat("%dms");
    m_chart->addAxis(axisX, Qt::AlignBottom);
    splineSeries->attachAxis(axisX);



    QValueAxis* axisY = new QValueAxis();

    axisY->setRange(0, 1);
    axisY->setLabelFormat("%.2f");
    axisY->setTickCount(8);

    axisY->setGridLineVisible(false);
    axisY->applyNiceNumbers();
    m_chart->addAxis(axisY, Qt::AlignLeft);
    splineSeries->attachAxis(axisY);




    m_chart->legend()->hide();
    m_chart->setTitle(m_title);


    foreach(QLegendMarker * marker, m_chart->legend()->markers()) {
        QObject::disconnect(marker, SIGNAL(clicked()), this, SLOT(on_LegendMarkerClicked()));
        QObject::connect(marker, SIGNAL(clicked()), this, SLOT(on_LegendMarkerClicked()));
    }
}

void ChartPane::setData(const QMap<QString, QMap<QString, long long>>& barData)
{
    clear();
    m_chartData = barData;
    analyseData(m_chartData, m_minValue, m_maxValue);
}

void ChartPane::setSplineData()
{
    clear();
    m_dealData.initDB();
    m_dealData.initSplinData(m_sFile);
    m_chartSplineData = m_dealData.getSplineData();
    m_barDatas = m_dealData.getNormalityDtata();
    m_nMax = m_dealData.getSplieMaxData();
    m_dealData.disDB();
}

void ChartPane::setLabels(const QStringList& labels)
{
    m_labels = labels;

    buildModel(m_chartData, m_labels, m_model);
}

void ChartPane::setYLabel(const QString& yLabel)
{
    m_label = yLabel;
}

void ChartPane::setOrientation(BarOrientation orientation)
{
    m_barOrientation = orientation;
}

void ChartPane::setPorssBarValue(int nData1, int nData2, int nDataMax2)
{
    ui->pgBar_data->setValue(nData1);
    ui->pgBar_parse->setMaximum(nDataMax2);
    ui->pgBar_parse->setValue(nData2);
}

void ChartPane::showUI()
{
    ui->btn_down->hide();
    ui->btn_up->hide();
    ui->pgBar_data->show();
    ui->pgBar_parse->show();
}

QT_CHARTS_NAMESPACE::QChart* ChartPane::chart()
{
    return m_chart;
}

void ChartPane::init()
{
    ui->chartInfo->hide();
    m_chart = new QChart();
    m_chart->setTheme(QChart::ChartThemeQt);
    m_chart->setMargins(QMargins(6, 6, 6, 6));
    m_chart->setAnimationOptions(QChart::SeriesAnimations);

    m_chart->setTheme(QChart::ChartThemeLight);
    m_chart->setDropShadowEnabled(true);
    m_chart->setAutoFillBackground(true);
    m_chart->legend()->setVisible(true);
    m_chart->legend()->setAlignment(Qt::AlignBottom);
    m_chart->legend()->setBackgroundVisible(true);
    m_chart->legend()->setAutoFillBackground(true);
    m_chart->legend()->setColor(QColor(222, 233, 251));
    m_chart->legend()->setLabelColor(QColor(0, 100, 255));
    m_chart->legend()->setMaximumHeight(50);

    ui->chartViewBar->setChart(m_chart);
    ui->chartViewBar->setRenderHint(QPainter::Antialiasing);
    m_model = new QStandardItemModel(this);
    m_barOrientation = VERTICAL_BAR;

    ui->toolBox->hide();
}
void ChartPane::clear()
{
    m_chartData.clear();
    m_chartSplineData.clear();
    clearChartUI();

    if (Q_NULLPTR != m_model)
    {
        m_model->clear();
    }

    m_label.clear();
    m_labels.clear();
    m_minValue = 0;
    m_maxValue = 0;
}

void ChartPane::clearChartUI()
{
    if (Q_NULLPTR != m_chart)
    {
        m_chart->removeAllSeries();
        m_chart->removeAxis(m_chart->axisX());
        m_chart->removeAxis(m_chart->axisY());
    }
}

void ChartPane::dealData()
{
    ui->pgBar_parse->hide();
    ui->pgBar_data->hide();
    m_dealData.m_nRow = m_nRow;
    switch (m_nType) {
    case 0:
        m_dealData.splitLineData();
        setData(m_dealData.getLineData());
        drawLine();
        break;
    case 1:
        m_dealData.splitBarData();
        setData(m_dealData.getBarData());
        drawBar();
        break;
    case 2:
        setSplineData();
        drawSpline();
        break;
    default:
        break;
    }
    m_nRow = m_dealData.m_nRow;
}

QStringList ChartPane::autoGenLabels(const QMap<QString, QMap<QString, long long>>& data)
{
    QSet<QString> labels;
    foreach(QString dataKey, data.keys())
    {
        QSet<QString> curLabels = data.value(dataKey).keys().toSet();
        labels = labels + curLabels;
    }

    return labels.toList();
}

void ChartPane::analyseData(const QMap<QString, QMap<QString, long long>>& data,
                            long long& minVlue, long long& maxValue)
{
    foreach(QString XKey, data.keys())
    {
        foreach(QString YKey, data.value(XKey).keys())
        {
            if (minVlue > data.value(XKey).value(YKey))
            {
                minVlue = data.value(XKey).value(YKey);
            }
            if (maxValue < data.value(XKey).value(YKey))
            {
                maxValue = data.value(XKey).value(YKey);
            }
        }
    }
}

void ChartPane::buildModel(const QMap<QString, QMap<QString, long long>>& data,
                           const QStringList& labels, QStandardItemModel* model)
{
    model->setColumnCount(labels.length());
    model->setRowCount(data.size());
    model->setHorizontalHeaderLabels(labels);
    model->setVerticalHeaderLabels(data.keys());

    int nRow = 0;
    foreach(QString dataKey, data.keys())
    {
        int nCol = 0;
        foreach(QString label, labels)
        {
            long long value = data.value(dataKey).value(label);
            QStandardItem* aItem = new QStandardItem(value);
            aItem->setData(QVariant::fromValue(value));
            model->setItem(nRow, nCol, aItem);
            nCol++;
        }
        nRow++;
    }
}

void ChartPane::setTitle(const QString& title)
{
    m_title = title;
}

void ChartPane::on_btn_styleSet_clicked()
{
    if (ui->toolBox->isVisible())
    {
        ui->toolBox->hide();
        ui->btn_styleSet->setText(tr("Set"));
    }
    else
    {
        ui->toolBox->show();
        ui->btn_styleSet->setText(tr("Close Set"));
    }
}

void ChartPane::on_LegendMarkerClicked()
{
    QLegendMarker* marker = qobject_cast<QLegendMarker*> (sender());

    switch (marker->type())
    {
    case QLegendMarker::LegendMarkerTypeBar:
    {
        marker->series()->setVisible(!marker->series()->isVisible());
        marker->setVisible(true);
        qreal alpha = 1.0;
        if (!marker->series()->isVisible())
            alpha = 0.5;

        QColor color;
        QBrush brush = marker->labelBrush();
        color = brush.color();
        color.setAlphaF(alpha);
        brush.setColor(color);
        marker->setLabelBrush(brush);

        brush = marker->brush();
        color = brush.color();
        color.setAlphaF(alpha);
        brush.setColor(color);
        marker->setBrush(brush);

        QPen pen = marker->pen();
        color = pen.color();
        color.setAlphaF(alpha);
        pen.setColor(color);
        marker->setPen(pen);
        break;
    }
    default:
        break;
    }
}

void ChartPane::on_btnSetTitle_clicked()
{
    QString str = ui->editTitle->text();
    ui->chartViewBar->chart()->setTitle(str);
}

void ChartPane::on_btnSetTitleFont_clicked()
{

    QFont font = ui->chartViewBar->chart()->titleFont();
    bool  ok = false;
    font = QFontDialog::getFont(&ok, font);
    if (ok)
        ui->chartViewBar->chart()->setTitleFont(font);
}

void ChartPane::on_btnSetMargin_clicked()
{
    QMargins    mgs;
    mgs.setLeft(ui->spinMarginLeft->value());
    mgs.setRight(ui->spinMarginRight->value());
    mgs.setTop(ui->spinMarginTop->value());
    mgs.setBottom(ui->spinMarginBottom->value());
    ui->chartViewBar->chart()->setMargins(mgs);
}

void ChartPane::on_chkBarLabelVisible_clicked(bool checked)
{
    if (m_barOrientation == VERTICAL_BAR)
    {
        curSeries->setLabelsVisible(checked);
    }
    else
    {
        curHorSeries->setLabelsVisible(checked);
    }
}

void ChartPane::on_radioButton_middle_clicked()
{
    if (m_barOrientation == VERTICAL_BAR)
    {
        curSeries->setLabelsPosition(QAbstractBarSeries::LabelsCenter);
    }
    else
    {
        curHorSeries->setLabelsPosition(QAbstractBarSeries::LabelsCenter);
    }
}

void ChartPane::on_radioButton_top_clicked()
{
    if (m_barOrientation == VERTICAL_BAR)
    {
        curSeries->setLabelsPosition(QAbstractBarSeries::LabelsInsideEnd);
    }
    else
    {
        curHorSeries->setLabelsPosition(QAbstractBarSeries::LabelsInsideEnd);
    }
}

void ChartPane::on_radioButton_bottom_clicked()
{
    if (m_barOrientation == VERTICAL_BAR)
    {
        curSeries->setLabelsPosition(QAbstractBarSeries::LabelsInsideBase);
    }
    else
    {
        curHorSeries->setLabelsPosition(QAbstractBarSeries::LabelsInsideBase);
    }
}

void ChartPane::on_radioButton_out_clicked()
{
    if (m_barOrientation == VERTICAL_BAR)
    {
        curSeries->setLabelsPosition(QAbstractBarSeries::LabelsOutsideEnd);
    }
    else
    {
        curHorSeries->setLabelsPosition(QAbstractBarSeries::LabelsOutsideEnd);
    }
}

void ChartPane::on_chkLegendVisible_clicked(bool checked)
{
    ui->chartViewBar->chart()->legend()->setVisible(checked);
}

void ChartPane::on_btnSetAxisRange_clicked()
{
    curAxis->setRange(ui->spinAxisMin->value(), ui->spinAxisMax->value());
}

void ChartPane::on_spinTickCount_valueChanged(int arg1)
{
    curAxis->setTickCount(arg1);
}

void ChartPane::on_spinMinorTickCount_valueChanged(int arg1)
{
    curAxis->setMinorTickCount(arg1);
}

void ChartPane::on_checkBox_clicked(bool checked)
{
    curAxis->setLineVisible(checked);
}

void ChartPane::on_chkGridLineVisible_clicked(bool checked)
{
    curAxis->setGridLineVisible(checked);
}

void ChartPane::on_chkMinorTickVisible_clicked(bool checked)
{

    curAxis->setMinorGridLineVisible(checked);
}

void ChartPane::on_chkBoxLegendBackground_clicked(bool checked)
{

    ui->chartViewBar->chart()->legend()->setBackgroundVisible(checked);
}

void ChartPane::on_radioButton_clicked()
{

    ui->chartViewBar->chart()->legend()->setAlignment(Qt::AlignTop);
}

void ChartPane::on_radioButton_2_clicked()
{

    ui->chartViewBar->chart()->legend()->setAlignment(Qt::AlignBottom);
}

void ChartPane::on_radioButton_3_clicked()
{

    ui->chartViewBar->chart()->legend()->setAlignment(Qt::AlignLeft);
}

void ChartPane::on_radioButton_4_clicked()
{

    ui->chartViewBar->chart()->legend()->setAlignment(Qt::AlignRight);
}

void ChartPane::on_btnLegendFont_clicked()
{

    QFont font = ui->chartViewBar->chart()->legend()->font();
    bool  ok = false;
    font = QFontDialog::getFont(&ok, font);
    if (ok)
        ui->chartViewBar->chart()->legend()->setFont(font);
}

void ChartPane::on_btnLegendlabelColor_clicked()
{

    QColor  color = ui->chartViewBar->chart()->legend()->labelColor();
    color = QColorDialog::getColor(color);
    if (color.isValid())
        ui->chartViewBar->chart()->legend()->setLabelColor(color);
}

void ChartPane::on_chkBoxVisible_clicked(bool checked)
{

    curAxis->setVisible(checked);
}

void ChartPane::on_btnAxisSetTitle_clicked()
{

    curAxis->setTitleText(ui->editAxisTitle->text());
}

void ChartPane::on_btnAxisSetTitleFont_clicked()
{

    QFont   font = curAxis->titleFont();

    bool    ok = false;
    font = QFontDialog::getFont(&ok, font);
    if (ok)
        curAxis->setTitleFont(font);
}

void ChartPane::on_chkBoxAxisTitle_clicked(bool checked)
{

    curAxis->setTitleVisible(checked);
}

void ChartPane::on_pushButton_clicked()
{

    curAxis->setLabelFormat(ui->editAxisLabelFormat->text());
}

void ChartPane::on_btnAxisLabelColor_clicked()
{

    QColor   color = curAxis->labelsColor();

    color = QColorDialog::getColor(color);
    if (color.isValid())
        curAxis->setLabelsColor(color);
}

void ChartPane::on_btnAxisLabelFont_clicked()
{

    QFont   font = curAxis->labelsFont();

    bool    ok = false;
    font = QFontDialog::getFont(&ok, font);
    if (ok)
        curAxis->setLabelsFont(font);
}

void ChartPane::on_chkBoxLabelsVisible_clicked(bool checked)
{
    curAxis->setLabelsVisible(checked);
}

void ChartPane::on_btnGridLineColor_clicked()
{

    QColor   color = curAxis->gridLineColor();

    color = QColorDialog::getColor(color);
    if (color.isValid())
        curAxis->setGridLineColor(color);
}

void ChartPane::on_pushButton_10_clicked()
{

    QPen    pen;
    pen = curAxis->gridLinePen();

    bool    ok = false;
    pen = QWDialogPen::getPen(pen, ok);

    if (ok)
        curAxis->setGridLinePen(pen);
}

void ChartPane::on_chkAxisLineVisible_clicked(bool checked)
{

    curAxis->setLineVisible(checked);
}

void ChartPane::on_btnAxisLinePen_clicked()
{
    QPen    pen;
    pen = curAxis->linePen();

    bool    ok = false;
    pen = QWDialogPen::getPen(pen, ok);

    if (ok)
        curAxis->setLinePen(pen);
}

void ChartPane::on_btnAxisLinePenColor_clicked()
{
    QColor   color = curAxis->linePenColor();

    color = QColorDialog::getColor(color);
    if (color.isValid())
        curAxis->setLinePenColor(color);
}

void ChartPane::on_btnMinorColor_clicked()
{

    QColor   color = curAxis->minorGridLineColor();

    color = QColorDialog::getColor(color);
    if (color.isValid())
        curAxis->setMinorGridLineColor(color);
}

void ChartPane::on_btnMinorPen_clicked()
{

    QPen    pen;
    pen = curAxis->minorGridLinePen();

    bool    ok = false;
    pen = QWDialogPen::getPen(pen, ok);

    if (ok)
        curAxis->setMinorGridLinePen(pen);
}

void ChartPane::on_cBoxAnimation_currentIndexChanged(int index)
{

    ui->chartViewBar->chart()->setAnimationOptions(QChart::AnimationOptions(index));
}

void ChartPane::on_cBoxTheme_currentIndexChanged(int index)
{
    ui->chartViewBar->chart()->setTheme(QChart::ChartTheme(index));
}

void ChartPane::on_actZoomIn_triggered()
{

    ui->chartViewBar->chart()->zoom(1.2);//zoomIn();
}

void ChartPane::on_actZoomOut_triggered()
{

    ui->chartViewBar->chart()->zoom(0.8);//zoomOut();
}

void ChartPane::on_actZoomReset_triggered()
{

    ui->chartViewBar->chart()->zoomReset();
}

void ChartPane::on_btn_up_clicked()
{
    QSettings settings;
    int data_size = settings.value("chartSetting/data_size", 0).toInt();

    m_nIndex -= data_size;
    if (m_nIndex <= 0)
    {
        m_nIndex = 0;
        ui->btn_up->setEnabled(false);
    }
    if (m_vIndexs.size() <= 3)
    {
        m_nRow = 0;
    }
    else {
        m_nRow = m_vIndexs[m_vIndexs.size() - 3];
        m_vIndexs.remove(m_vIndexs.size() - 1);
    }
    dealData();
}


void ChartPane::on_btn_down_clicked()
{
    QSettings settings;
    int data_size = settings.value("chartSetting/data_size", 0).toInt();
    m_nIndex += data_size;
    if (m_nIndex > 0)
    {
        ui->btn_up->setEnabled(true);
    }
    m_nRow = m_vIndexs.size() == 1 ? 0 : m_vIndexs.last();
    dealData();
    if (m_nRow == m_vIndexs.last())
    {
        if (m_dealData.m_bPos)
        {
            m_dealData.fetchMore();
        }
        else {
            ui->btn_down->setEnabled(false);
            QMessageBox::information(NULL, tr("Title"), tr("No more records"), QMessageBox::Yes | QMessageBox::No);
        }
    }
    else {
        m_vIndexs.push_back(m_nRow);
    }
}

